package editor.dxf;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JFrame;

import org.kabeja.Tests;
import org.kabeja.dxf.DXFArc;
import org.kabeja.dxf.DXFCircle;
import org.kabeja.dxf.DXFConstants;
import org.kabeja.dxf.DXFDocument;
import org.kabeja.dxf.DXFLayer;
import org.kabeja.dxf.DXFLine;
import org.kabeja.dxf.DXFText;
import org.kabeja.dxf.helpers.Point;
import org.kabeja.parser.DXFParser;
import org.kabeja.parser.ParseException;
import org.kabeja.parser.Parser;
import org.kabeja.parser.ParserBuilder;

import editor.graphics.Dibujable;
import editor.graphics.EditorMapa;
import editor.modelo.EditorFloor;
import editor.modelo.EditorPortal;
import editor.modelo.EditorSpace;
import editor.modelo.Portal;

public class DxfModel implements Dibujable {

	private static int scale = 40;
	private static int checkLong = 12; //para 100 es 7
	private static int checkTrans = 20; //para 100 es 5
	
	private static final String CAPA_IDS = "NOMENCLATURA";
	private static final String CAPA_ARCOS_PUERTAS = "00-CARP-MANO-ABRIR";
	private static final String CAPA_HOJAS_PUERTAS = "00-CARP-HOJAS-PUERTAS";
	private static final String CAPA_NAMES = "00-TEXTO-30";
	private static final String[] CAPAS_PAREDES = new String[] { "00-M-A-100", "00-M-A-150",
		"00-M-A-200",
			"00-M-A-300", "00-M-A-450",  "00-M-A-400", "00-CARP-VENTANAS",
			"00-CARP-SIMBOLOGIA", "00-CARP-DETALLES",
			"00-LOCALES-R-PUERTAS", "00-CARP-VEN-ANTEPECHO", "00-ESCALERA",
			 };

	//PARAMETROS DEPENDIENTES DE CADA MAPA
	private transient String file;
	private String ID;
	transient private int FIXX = 0;
	transient private int FIXY = 0;
	transient private int WDT = 0;
	transient private int HGT = 0;
	private int offsetX = 0; //tienen que ser 0... estan mal programados
	private int offsetY = 0;
	private double rotation = -Math.PI / 2;
	private float MapScaleX;
	private float MapScaleY;
	
	//Variables "caras" compartidas por todos los metodos del objeto, se inicializan en el read.
	transient private float scalebyX;
	transient private float scalebyY;
	
	private transient BufferedImage img = null;
	private transient SpaceParser spaceParser;
	private transient DXFLayer layer = null;
	private transient DXFDocument doc = null;
	private transient List<DXFText> spaceIds = null; 
	private transient List<DXFText> spaceNames = null; 
	
	public DxfModel(){
		
	}
	public DxfModel(String id, float MapScaleX, float MapScaleY, int grados) {
		this.ID = id;
		this.rotation = Math.PI * grados / 180.0f;
		this.MapScaleX = MapScaleX;
		this.MapScaleY = MapScaleY;
	//	this.scalebyX = Math.round(MapScaleX * (scale)/1000f);
	//	this.scalebyY = Math.round(MapScaleY * (scale)/1000f);
	}

	
	private void generarEstado(){
		this.scalebyX = Math.round(MapScaleX * (scale)/1000f);
		this.scalebyY = Math.round(MapScaleY * (scale)/1000f);
	
		createDocument(file); //OJO con esto: es importante el orden de estas inst.
		if(WDT == 0) //lo calcula 1 sola vez "automaticamente", para q el usuario 
					//lo pueda cambiar y no se borre
			calculateDimmensions();
		System.out.println("calc inicial: "+ WDT + " " + HGT + " " + FIXX + " " + FIXY);
		img = new BufferedImage(WDT, HGT, Transparency.BITMASK);
		
		int[] rgbs = new int[WDT*HGT];
		img.getRGB(0, 0, WDT, HGT, rgbs, 0, WDT);
		Arrays.fill(rgbs, 255);
		Graphics2D g2 = img.createGraphics();
		printDocInImage(g2); //carga la imagen
		g2.dispose();
		
		Image scaledImage = img.getScaledInstance((int)(WDT*(100f/scale)),
				(int)(HGT*(100f/scale)), Image.SCALE_FAST);
        img = new BufferedImage((int)(WDT*(100f/scale)), 
        		(int)(HGT*(100f/scale)), Transparency.BITMASK);
        g2 = img.createGraphics();
        g2.drawImage(scaledImage, 0, 0, null);
       
        
        scalebyX *= 100f/scale; 
        scalebyY *= (100f/scale); 
        FIXX *= (100f/scale);
        FIXX += 5;
        FIXY *= (100f/scale); 
        System.out.println("calc final: "+ WDT + " " + HGT + " " + FIXX + " " + FIXY);
      
        reconocerPuertas(g2);
		cargarTextos(g2);
		spaceParser = new SpaceParser(img); //ESTA LISTO PARA PARSEAR CON ESTE OBJETO 
		g2.dispose();
	}
	

	public void createDocument(String in){
		Parser parser = ParserBuilder.createDefaultParser();
		try {
			parser.parse(in, DXFParser.DEFAULT_ENCODING);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		doc = parser.getDocument();
	}
	
	public void printDocInImage(Graphics2D g) {
		// /////////////////////PORTALES /////////////////////////////////
		layer = doc.getDXFLayer(CAPA_HOJAS_PUERTAS);
		List<DXFDoor> puertas = extractPuertas(layer);

		layer = doc.getDXFLayer(CAPA_ARCOS_PUERTAS);
		// agregarArcos(layer, g);
		completarPuertasArcos(layer, puertas); // genera el modelo de las
												// puertas completo (cerradas)
		g.setColor(Color.BLUE);
	
		for (DXFDoor puerta : puertas) {
			if (puerta.getAdyacent() != null)
				g.drawLine((int) (puerta.getBisagra().getX()),
						(int) (puerta.getBisagra().getY()),
						(int) (puerta.getAdyacent().getX()),
						(int) (puerta.getAdyacent().getY()));
		}
		
		g.setColor(Color.RED);
		agregarLineas(layer, g); //agrega las puertas que se hacen con una linea

		// ///////////////////PAREDES ///////////////////////////////////
		g.setColor(Color.BLACK);
		for (String s : CAPAS_PAREDES) {
			layer = doc.getDXFLayer(s);
			agregarLineas(layer, g);
			agregarArcos(layer, g);
		}
		// ///////////////////PAREDES ///////////////////////////////////
		// ///TERMINA CON LA PRIMERA PASADA DE LA IMAGEN

		
	
		
	/*	List<DXFCircle> arcs = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_CIRCLE);
		if (arcs != null) {
			for (DXFCircle arc : arcs) {
				List<Point2D.Float> borde = sp.generateSpace((int)(arc.getCenterPoint().getX() *scaleby) + FIXX, 
						-(int)(arc.getCenterPoint().getY() * scaleby) + FIXY);
				
				for(int i = 0; i<borde.size()-1; i++){
					g.drawLine((int)borde.get(i).getX(),
							(int)borde.get(i).getY(),
							(int)borde.get(i+1).getX(),
							(int)borde.get(i+1).getY());
				}
				g.drawLine((int)borde.get(0).getX(),
						(int)borde.get(0).getY(),
						(int)borde.get(borde.size()-1).getX(),
						(int)borde.get(borde.size()-1).getY());
				
			}
		}*/
		
//		g.drawOval(550, 664, 10, 10);
	
		/*	
		g.setColor(Color.GREEN);
		for (DXFDoor puerta : puertasLeidas) {
			if (puerta.getAdyacent() != null)
				g.drawLine((int) (puerta.getBisagra().getX()),
						(int) (puerta.getBisagra().getY()),
						(int) (puerta.getAdyacent().getX()),
						(int) (puerta.getAdyacent().getY()));
		}*/


		/*
		 * g.setColor(Color.GREEN); for(DXFDoor puerta: puertasLeidas){
		 * g.drawLine((int) (puerta.getBisagra().getX() ), (int)
		 * (puerta.getBisagra().getY()), (int) (puerta.getEnd().getX()) , (int)
		 * (puerta.getEnd().getY())); }
		 */

	}
	private void reconocerPuertas(Graphics2D g) {
		// /Reconozco las puertas que se pintaron recien (las dobles las une)
		List<DXFDoor> puertasLeidas = new DoorParser(img).leerPuertas();
		// g.drawString("X", (int)489, (int)510);

		g.setColor(Color.RED);
//		System.out.println("Puertas reconocidas :" + puertas.size() + " de " + 
//				puertasLeidas.size() + " (las dobles se cuentan como 1 en las reconocidas)");
		for (DXFDoor puerta : puertasLeidas) {
			if (puerta.getAdyacent() != null)
				pintarPuertaAcomodada(puerta, g, img);
		}
	}
	
	/*
	 * Agrega el space al piso y lo devuelve
	 */
	public EditorSpace generarSpace(int x, int y, EditorFloor piso){
		EditorSpace espacio = piso.addNewSpace((int)(x -offsetX), y - offsetY);
		spaceParser.generateSpace(x -offsetX,  y - offsetY);
		espacio.setBorde(spaceParser.getContorno());
		espacio.calculateBoundingBox();
	
		
		String name = "";
		for(DXFText t: spaceNames){
			if(espacio.contains((int)t.getInsertPoint().getX(), (int)t.getInsertPoint().getY())){
				if(name.equals(""))
					name = (t.getText());
				else name +=(" " +t.getText());
			}
		}
		
		espacio.setName(name);
		
		String id = "";
		for(DXFText t: spaceIds){
			if(espacio.contains((int)t.getInsertPoint().getX(), (int)t.getInsertPoint().getY())){
				if(id.equals(""))
					id= t.getText();
				else id +=  " " +t.getText();
			}
		}
		espacio.setId(id); //este id es para ver si es up o dw.. despues lo blanqueo y lo autogenero

		espacio.move(offsetX, offsetY);
		for(Point2D portal : spaceParser.getPortals()){
			EditorPortal port=	piso.addNewUnlinkedPortal(espacio, portal);
			if(espacio.getId().equals("up"))
			{
				port.setTipo(Portal.Tipo.ustair);
				int altura = EditorFloor.ALTURA_NIVEL>>1;
				port.setDifferential(altura);
			}
			if(espacio.getId().equals("dw"))
			{
				port.setTipo(Portal.Tipo.dstair);
				int altura = EditorFloor.ALTURA_NIVEL>>1;
				port.setDifferential(altura);
			}
		}
		espacio.setId(""); //si lo mando vacio le pone uno automatico
		piso.validateID(espacio);//cambiar metodo
		return espacio;
	//	g.drawOval(x -offsetX , y - offsetY, 10, 10);
	}

	public void generateFloor(EditorFloor piso){
		for(DXFText t: spaceIds){
			System.out.println(t.getText()+" "+ (int)t.getInsertPoint().getX() + " "
					+ (int)t.getInsertPoint().getY());
			EditorSpace espacio = this.generarSpace((int)t.getInsertPoint().getX() + offsetX, 
					(int)t.getInsertPoint().getY() + offsetY,
					piso);
			espacio.setId(""); //si lo mando vacio le pone uno automatico
			piso.validateID(espacio);//cambiar metodo
		}
	}
	
	
	private void cargarTextos(Graphics2D g) {
		layer = doc.getDXFLayer(CAPA_NAMES);
		spaceNames = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_TEXT);
		if(spaceNames == null) spaceNames = new ArrayList<DXFText>();
		correctCoords(spaceNames);

		layer = doc.getDXFLayer(CAPA_IDS);
		spaceIds =  layer.getDXFEntities(DXFConstants.ENTITY_TYPE_TEXT);
		if(spaceIds == null) spaceIds = new ArrayList<DXFText>();
		correctCoords(spaceIds);
		g.setColor(Color.BLUE);
		for(DXFText t: spaceIds){		
			g.drawRect((int)t.getInsertPoint().getX(), (int)t.getInsertPoint().getY(), 1, 1);
		}
	}

	private void correctCoords(List<DXFText> textos) {
		for(DXFText t: textos){
			t.getInsertPoint().setX((int)Math.round( toWorldCoordX( t.getInsertPoint().getX())));
			t.getInsertPoint().setY((int)Math.round( toWorldCoordY(t.getInsertPoint().getY())));	
		}
	}

	private void pintarPuertaAcomodada(DXFDoor puerta, Graphics2D g,
			BufferedImage img2) {
		Point2D.Float pmin, pmax;
		int xmin = -1;
		int xmax = -1;
		int ymax = -1;
		int ymin = -1;
		
		if (puerta.isHorizontal()) 
		{
			int barridoY = checkTrans;
			int barridoX = checkLong; //era 7
			
			// veo el limite izquierdo
			pmin = puerta.getBisagra().getX() < puerta.getAdyacent().getX() ? puerta
					.getBisagra() : puerta.getAdyacent();
			pmax = puerta.getBisagra().getX() >= puerta.getAdyacent().getX() ? puerta
					.getBisagra() : puerta.getAdyacent();

			for (int i = 0; i < barridoX; i++) {
				for (int j = 0; j < barridoY; j++) {
					if (isWall((int) pmin.getX() + barridoX / 2 - i,
							(int) pmin.getY() + barridoY / 2 - j)) {
						xmin = (int) pmin.getX() + barridoX / 2 - i + 1;
						break;
					}
				}
				if (xmin > 0)
						break;
			}
			if (xmin < 0) {
				System.out.println("no se encontro Xmin " + pmin.getX());
				g.setColor(Color.BLUE);
				g.drawString("X", (int) pmin.getX(), (int) -pmin.getY());
				g.setColor(Color.RED);
				xmin = (int) Math.round(pmin.getX());
				//return;
			}
			
			for (int i = 0; i < barridoX; i++) {
				for (int j = 0; j < barridoY; j++) {
					if (isWall((int) pmax.getX() - barridoX / 2 + i,
							(int) pmax.getY() + barridoY/2 - j)) // si no es negro,
														// encontre el limite
					{
						xmax = (int) pmax.getX() - (barridoX / 2) + i - 1;
						break;
					}
					}
					if (xmax > 0)
						break;
			}
			if (xmax < 0) {
				g.setColor(Color.BLUE);
				g.drawString("X", (int) pmax.getX(), (int) pmax.getY());
				g.setColor(Color.RED);
				System.out.println("no se encontro Xmax " + pmax.getX());
				//return;
				xmax = (int) Math.round(pmax.getX());
			}
			pmin.x = xmin;
			pmax.x = xmax;
			for (int i = 0; i < barridoY; i++) {
				if (isWall((int) pmin.getX() - 1, (int) pmin.getY() + barridoY	/ 2 - i)) {
					if (!isWall((int) pmin.getX() - 1, (int) pmin.getY()
							+ barridoY / 2 - i + 1)) {
						ymax = (int) pmin.getY() + barridoY / 2 - i;
						break;
					}
				}
				if (ymax > 0)
					break;
			}

			if (ymax < 0) { // busco en el otro extremo
				for (int i = 0; i < barridoY; i++) {
					if (isWall((int) pmax.getX() + 1, (int) pmax.getY()
							+ barridoY / 2 - i)) {
						if (!isWall((int) pmax.getX() + 1, (int) pmax.getY()
								+ barridoY / 2 - i + 1)) {
							ymax = (int) pmax.getY() + barridoY / 2 - i;
							break;
						}
					}
					if (ymax > 0)
						break;
				}
			}
			if (ymax < 0) {
					System.out.println("no se encontro Ymax " + pmin.getX()
							+ " " + pmin.getY());
					g.setColor(Color.BLUE);
					g.drawString("X", (int) pmin.getX(), (int) -pmin.getY());
					g.setColor(Color.RED);
					ymax = (int) Math.round(pmax.getY());
					//return;
				}
			for (int i = 0; i < barridoY; i++) {
				if (isWall((int) pmin.getX() - 1, (int) pmin.getY() - barridoY
						/ 2 + i)) {
					if (!isWall((int) pmin.getX() - 1, (int) pmin.getY()
							- barridoY / 2 + i - 1)) {
						ymin = (int) pmin.getY() - barridoY / 2 + i;
						break;
					}
				}
				if (ymin > 0)
					break;
			}

			if (ymin < 0) { // busco en el otro extremo
				for (int i = 0; i < barridoY; i++) {
					if (isWall((int) pmax.getX() + 1, (int) pmax.getY()
							- barridoY / 2 + i)) // si no es negro, encontre el
													// limite
					{
						if (!isWall((int) pmax.getX() + 1, (int) pmax.getY()
								- barridoY / 2 + i - 1)) {
							ymin = (int) pmax.getY() - barridoY / 2 + i;
							break;
						}
					}
					if (ymin > 0)
						break;
				}
			}
			if(ymin <0 ){
				  System.out.println("no se encontro Ymin");
				  g.setColor(Color.BLUE);
				  g.drawString("X", (int)pmin.getX(), (int)-pmin.getY());
				  g.setColor(Color.RED); 
				  ymin = (int) Math.round(pmax.getY());
				  return; 
			}
		}
		else //es vertical
		{
			int barridoX = checkTrans;
			int barridoY = checkLong; //era 7
			
			// veo el limite menor
			pmin = puerta.getBisagra().getY() < puerta.getAdyacent().getY() ? puerta
					.getBisagra() : puerta.getAdyacent();
			pmax = puerta.getBisagra().getY() >= puerta.getAdyacent().getY() ? puerta
					.getBisagra() : puerta.getAdyacent();

				for (int j = 0; j < barridoY; j++) {
					for (int i = 0; i < barridoX; i++) {
						if (isWall(
							(int) pmin.getX() + barridoX / 2 - i,
							(int) pmin.getY() + barridoY / 2 - j)
							) {
							ymin = (int) pmin.getY() + barridoY / 2 - j + 1;
							break;
						}
					}
					if (ymin > 0)
						break;
				}
			if (ymin < 0) {
				System.out.println("no se encontro Ymin " + pmin.getX());
				g.setColor(Color.BLUE);
				g.drawString("X", (int) pmin.getX(), (int) -pmin.getY());
				g.setColor(Color.RED);
				ymin = (int) Math.round(pmin.getY());
			//	return;
			}
	
			for (int j = 0; j < barridoY; j++) {
				for (int i = 0; i < barridoX; i++) {
					if (isWall((int) pmax.getX() - barridoX / 2 + i,
							(int) pmax.getY() - barridoY/2 + j)) 
					{
						ymax = (int) pmax.getY() - barridoY / 2 + j - 1;
						break;
					}
					
				}if (ymax > 0)
						break;
			}
			if (ymax < 0) {
				g.setColor(Color.BLUE);
				g.drawString("X", (int) pmax.getX(), (int) pmax.getY());
				g.setColor(Color.RED);
				System.out.println("no se encontro ymax " + pmax.getY());
				ymax = (int) Math.round(pmax.getY());
				//return;
			}
			pmin.y = ymin;
			pmax.y = ymax;
			//xmax
			for (int i = 0; i < barridoX; i++) {
				if (isWall((int) pmin.getX() + barridoX / 2 - i , 
						(int) pmin.getY() - 1)) {
					if (!isWall((int) pmin.getX() + barridoX / 2 - i + 1, 
							(int) pmin.getY() -1)) {
						xmax = (int) pmin.getX() + barridoX / 2 - i;
						break;
					}
				}
				if (xmax > 0)
					break;
			}
			if (xmax < 0) { // busco en el otro extremo
				for (int i = 0; i < barridoX; i++) {
					if (isWall((int) pmax.getX()  + barridoX / 2 - i,
							(int) pmax.getY() + 1)) {
						if (!isWall((int) pmax.getX()  + barridoX / 2 - i + 1,
								(int) pmax.getY() + 1)) {
							xmax = (int) pmax.getX() + barridoX / 2 - i;
							break;
						}
					}
					if (xmax > 0)
						break;
				}
			}
			if (xmax < 0) {
					System.out.println("no se encontro xmax " + pmin.getX()
							+ " " + pmin.getY());
					g.setColor(Color.BLUE);
					g.drawString("X", (int) pmin.getX(), (int) -pmin.getY());
					g.setColor(Color.RED);
					xmax = (int) Math.round(pmax.getX());
					//return;
				}
				//xmin
			for (int i = 0; i < barridoX; i++) {
				if (isWall((int) pmin.getX() - barridoX	/ 2 + i,
						   (int) pmin.getY() -1 )) {
					if (!isWall((int) pmin.getX() - barridoX / 2 + i - 1, 
							(int) pmin.getY() -1)) {
						xmin = (int) pmin.getX() - barridoX / 2 + i;
						break;
					}
				}
				if (xmin > 0)
					break;
			}
			if (xmin < 0) 
			for (int i = 0; i < barridoX; i++) {
				if (isWall((int) pmax.getX() - barridoX	/ 2 + i,
						   (int) pmax.getY()  + 1 )) {
					if (!isWall((int) pmax.getX() - barridoX / 2 + i - 1, 
							(int) pmax.getY() + 1)) {
						xmin = (int) pmax.getX() - barridoX / 2 + i;
						break;
					}
				}
				if (xmin > 0)
					break;
			}

			if(xmin <0 ){
				  System.out.println("no se encontro xmin");
				  g.setColor(Color.BLUE);
				  g.drawOval((int)xmax, (int)ymax,1,1);
				  g.drawOval((int)xmax, (int)ymin,1,1);
				  xmin = (int) Math.round(pmax.getX());
				  g.setColor(Color.RED); 
				 // return; 
				  }
			
		}
		/*
		 * Hago que tengan 1 px
		 */
		if(xmax - xmin > ymax-ymin){
			g.fillRect(xmin, (ymax + ymin) /2, xmax -xmin +1, 1);
		}else
		{
			g.fillRect((xmax + xmin) /2, ymin, 1, (ymax - ymin) + 1);
		}
		g.fillRect(xmin, ymin, xmax - xmin + 1, (ymax - ymin) + 1);
		//System.out.println(xmin + " " + xmax + " " + ymin + " " + ymax);
		/*
		 * g.drawLine((int) (puerta.getBisagra().getX()), (int)
		 * (puerta.getBisagra().getY() ), (int) (puerta.getAdyacent().getX()),
		 * (int) (puerta.getAdyacent().getY()));
		 */
	}
	
	private void completarPuertasArcos(DXFLayer layer, List<DXFDoor> puertas) {
		List<DXFArc> arcs = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_ARC);
		if (arcs != null) {
			for (DXFArc arc : arcs) {
				arc.getCenterPoint().setX(toWorldCoordX(arc.getCenterPoint().getX() ));
				arc.getCenterPoint().setY(toWorldCoordY(arc.getCenterPoint().getY()));
				arc.setRadius(arc.getRadius() * scalebyX);
				arc.setStartAngle(-arc.getStartAngle());
				arc.setEndAngle(-arc.getEndAngle());
				for (DXFDoor puerta : puertas) {
					if (puerta.addArc(arc))
						break;
				}
			}
		}
	}

	private List<DXFDoor> extractPuertas(DXFLayer layer) {
		Point2D.Float p1, p2;
		boolean b;
		ArrayList<DXFDoor> l = new ArrayList<DXFDoor>(255);
		@SuppressWarnings("unchecked")
		List<DXFLine> plines = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_LINE);
		if (plines != null)
			for (DXFLine line : plines) {
				p1 = new Point2D.Float(toWorldCoordX(line.getStartPoint().getX()),
						              toWorldCoordY(line.getStartPoint().getY()));
				p2 = new Point2D.Float(toWorldCoordX(line.getEndPoint().getX()),
						               toWorldCoordY(line.getEndPoint().getY()));
				if (!DXFDoor.isValid(p1, p2))
					continue; // es el ancho de la puerta

				b = false;
				for (DXFDoor puerta : l) {
					if (puerta.isEquivalent(p1, p2)) {
						// puerta.mergeLine(p1 , p2);
						b = true;
						break;
					}
				}
				if (!b)
					l.add(new DXFDoor(p1, p2));
			}
		return l;
	}

	private void agregarArcos(DXFLayer layer, Graphics2D g) {
		List<DXFArc> arcs = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_ARC);
		if (arcs != null) {
			for (DXFArc arc : arcs) {
				Arc2D a = new Arc2D.Float();
				// if(arc.getRadius()*scaleby < 10) continue;
				double start = (!arc.isCounterClockwise() ? arc.getStartAngle()
						: arc.getEndAngle());
				double end = (arc.isCounterClockwise() ? arc.getStartAngle()
						: arc.getEndAngle());
				double length = end > start ? end - start : end - start + 360;
				a.setArcByCenter(
						(toWorldCoordX(arc.getCenterPoint().getX())),
						(toWorldCoordY(arc.getCenterPoint().getY())),
						(arc.getRadius() * scalebyX), start, length, Arc2D.OPEN);
				g.draw(a);
			}
		}
	}

	private void agregarLineas(DXFLayer layer, Graphics2D g) {
		List<DXFLine> plines = layer.getDXFEntities(DXFConstants.ENTITY_TYPE_LINE);
		if (plines != null)
			for (DXFLine line : plines) {
				g.drawLine(
						(int) Math.round(toWorldCoordX(line.getStartPoint().getX())),
						(int) Math.round(toWorldCoordY(line.getStartPoint().getY())),
						(int) Math.round(toWorldCoordX(line.getEndPoint().getX())),
						(int) Math.round(toWorldCoordY(line.getEndPoint().getY())));
			}
	}
	public String getID() {
		return ID;
	}
	public void setID(String iD) {
		ID = iD;
	}
	public void setFile(String file){
		this.file = file;
	}
	
	
	public void setScalebyX(float scalebyX) {
		this.scalebyX = scalebyX;
	}
	public void setScalebyY(float scalebyY) {
		this.scalebyY = scalebyY;
	}
	public boolean isInitialized() {
		return img!= null;
	}

	public void initialize() {
		generarEstado();
	}

	private void calculateDimmensions() {
		this.WDT = (int) (Math.round(doc.getBounds(true).getWidth()*scalebyX)+10);
		this.HGT = (int) (Math.round(doc.getBounds(true).getHeight()*scalebyY)+10);
		this.FIXX = -(int) (doc.getBounds(true).getMinimumX()*scalebyX) + 1;
		this.FIXY = this.HGT + (int) (doc.getBounds(true).getMinimumY()*scalebyY) - 1;
	}

	public void setOffsetX(int offsetX) {
		this.offsetX = offsetX;
	}

	public void setOffsetY(int offsetY) {
		this.offsetY = offsetY;
	}

	public int getOffsetX() {
		return offsetX;
	}

	public int getOffsetY() {
		return offsetY;
	}

	public void move(int offX, int offY) {
		this.offsetX += offX;
		this.offsetY += offY;
	}

	public void dibujar2(Graphics2D g)  {
		try {
			throw new Exception("no se usa mas esto");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void dibujarSelccionado(Graphics2D g) {
		dibujar2(g);
	}

	@Override
	public void dibujar(Graphics2D g) {
		g.translate(offsetX, offsetY);
		g.rotate(rotation);
		//g.scale(scalebyX/20.0, scalebyY/20.0);
		g.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);
		//g.scale(20.0/scalebyX, 20.0/scalebyY);
		g.rotate(-rotation);
		g.translate(-offsetX, -offsetY); // revierto la transf
	}

	private boolean isWall(int x, int y){
		return isWall(x, y, img);
	}

	public static boolean isWall(int x, int y, BufferedImage img) {
		try {
			int c = img.getRGB(x, y);
			int red = (c & 0x00ff0000) >> 16;
			int green = (c & 0x0000ff00) >> 8;
			int blue = c & 0x000000ff;
			int alpha = (c>>24) & 0xff;
		
			if (red < 20 && blue < 20 && green < 20 && alpha == 255)
				return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public static boolean isEmpty(int x, int y, BufferedImage img) {
		try {
			int c = img.getRGB(x, y);
			int red = (c & 0x00ff0000) >> 16;
			int green = (c & 0x0000ff00) >> 8;
			int blue = c & 0x000000ff;
			int alpha = (c>>24) & 0xff;
			
			//es transparente  o azul
			if (alpha == 0 || red < 20 && green < 20 && blue > 250)
				return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(x + " " + y);
		}
		return false;
	}
	
	public static boolean isPortal(int x, int y, BufferedImage img) {
		try {
			int c = img.getRGB(x, y);
			int red = (c & 0x00ff0000) >> 16;
			int green = (c & 0x0000ff00) >> 8;
			//int blue = c & 0x000000ff;
		
			//es rojo
			if (red > 250 && green < 50)
				return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(x + " " + y);
		}
		return false;
	}

	public static boolean isEmpty(int[] pto, BufferedImage img2) {
		return isEmpty(pto[0], pto[1], img2);
	}

	public static boolean isPortal(int[] pto, BufferedImage img2) {
		return isPortal(pto[0], pto[1], img2);
	}
	
	public float toWorldCoordX(double p){
		//System.out.println("to wordl "+p + " " + scalebyX + " " + FIXX);
		return (float) (p * scalebyX + FIXX);
	}
	public float toWorldCoordY(double p){
		return (float) (-p * scalebyY + FIXY);
	}
	

}
